﻿#region MIT Licence
/*
 * Copyright (C) 2014 PdfCreative
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
 * and associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom 
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included 
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#endregion

using System;
using System.Collections.Generic;
using System.Text;

namespace PdfCreative.Pdf.Graphics
{
    /// <summary>
    /// The StaticPages class is a convenience class that provides access to standard page sizes.
    /// </summary>
    public static class StandardPages
    {
        // Private fields
        // ==============
        #region Private fields
        private static Rectangle[] _pages;
        #endregion



        // Public properties
        // =================
        #region Public properties
        /// <summary>
        /// Retrieves a standard ISO A0 page format.
        /// </summary>
        public static Rectangle A0 { get { return _pages[(int)PageCode.A0]; } }

        /// <summary>
        /// Retrieves a standard ISO A1 page format.
        /// </summary>
        public static Rectangle A1 { get { return _pages[(int)PageCode.A1]; } }

        /// <summary>
        /// Retrieves a standard ISO A2 page format.
        /// </summary>
        public static Rectangle A2 { get { return _pages[(int)PageCode.A2]; } }

        /// <summary>
        /// Retrieves a standard ISO A3 page format.
        /// </summary>
        public static Rectangle A3 { get { return _pages[(int)PageCode.A3]; } }

        /// <summary>
        /// Retrieves a standard ISO A4 page format.
        /// </summary>
        public static Rectangle A4 { get { return _pages[(int)PageCode.A4]; } }

        /// <summary>
        /// Retrieves a standard ISO A5 page format.
        /// </summary>
        public static Rectangle A5 { get { return _pages[(int)PageCode.A5]; } }

        /// <summary>
        /// Retrieves a standard ISO A6 page format.
        /// </summary>
        public static Rectangle A6 { get { return _pages[(int)PageCode.A6]; } }

        /// <summary>
        /// Retrieves a standard US legal page format.
        /// </summary>
        public static Rectangle Legal { get { return _pages[(int)PageCode.Legal]; } }

        /// <summary>
        /// Retrieves a standard US letter page format.
        /// </summary>
        public static Rectangle Letter { get { return _pages[(int)PageCode.Letter]; } }

        /// <summary>
        /// Retrieves a standard US tabloid page format.
        /// </summary>
        public static Rectangle Tabloid { get { return _pages[(int)PageCode.Tabloid]; } }

        #endregion



        // Private implementation
        // ======================
        #region Private implementation
        /// <summary>
        /// Retrieves the page specification of a page code. The pagespecification is represented
        /// by the Page attribute that decorates the fields of the PageCode enumeration.
        /// </summary>
        /// <param name="pageCode">The page code.</param>
        /// <returns>The page specification.</returns>
        private static PageAttribute GetPageSpecification(PageCode pageCode)
        {
            PageAttribute result = null;

            System.Reflection.FieldInfo fieldInfo = pageCode.GetType().GetField(pageCode.ToString());
            foreach (PageAttribute attr in fieldInfo.GetCustomAttributes(typeof(PageAttribute), true))
            {
                result = attr; break;
            }

            return result;
        }

        /// <summary>
        /// Sets up the standard pages.
        /// </summary>
        private static void SetupPages()
        {
            int count = Enum.GetValues(typeof(PageCode)).Length;

            _pages = new Rectangle[count];

            for (int page = 0; page < count; page++)
            {
                // Retrieve the colour specification for this colour.
                PageAttribute pageSpec = GetPageSpecification((PageCode)page);

                // Create the colour, and a pen and brush that match it.
                _pages[page] = new Rectangle(0, 0, pageSpec.Width, pageSpec.Height);
            }
        }
        #endregion



        // Static constructor
        // ==================
        #region Static constructor
        /// <summary>
        /// Sets up the StandardPages class.
        /// </summary>
        static StandardPages()
        {
            SetupPages();
        }
        #endregion



        // Private types
        // =============
        #region PageCode enumeration
        /// <summary>
        /// The PageCode enumeration lists the pages that can be retrieved by the StandardPages
        /// class.
        /// </summary>
        private enum PageCode
        {
            /// <summary>
            /// A standard ISO A0 page format.
            /// </summary>
            [Page(Width = 2384, Height = 3370)]
            A0,

            /// <summary>
            /// A standard ISO A1 page format.
            /// </summary>
            [Page(Width = 1684, Height = 2384)]
            A1,

            /// <summary>
            /// A standard ISO A2 page format.
            /// </summary>
            [Page(Width = 1191, Height = 1684)]
            A2,

            /// <summary>
            /// A standard ISO A3 page format.
            /// </summary>
            [Page(Width = 842, Height = 1191)]
            A3,

            /// <summary>
            /// A standard ISO A4 page format.
            /// </summary>
            [Page(Width = 595, Height = 842)]
            A4,

            /// <summary>
            /// A standard ISO A5 page format.
            /// </summary>
            [Page(Width = 420, Height = 595)]
            A5,

            /// <summary>
            /// A standard ISO A6 page format.
            /// </summary>
            [Page(Width = 298, Height = 420)]
            A6,

            /// <summary>
            /// The US legal format.
            /// </summary>
            [Page(Width = 612, Height = 1009)]
            Legal,

            /// <summary>
            /// The US letter format.
            /// </summary>
            [Page(Width = 612, Height = 791)]
            Letter,

            /// <summary>
            /// The US tabloid format.
            /// </summary>
            [Page(Width = 791, Height = 1225)]
            Tabloid
        }
        #endregion

        #region PageAttribute class
        /// <summary>
        /// The PageAttribute class represent the Page attribute that is used to decorate fields
        /// of the PageCode enumeration. It links a PageCode field to a page size.
        /// </summary>
        [AttributeUsage(AttributeTargets.Field)]
        private class PageAttribute : Attribute
        {
            // Private fields
            // ==============
            #region Private fields
            private int _width;
            private int _height;
            #endregion



            // Public properties
            // =================
            #region Public properties
            /// <summary>
            /// Sets or retrieves the width of the page.
            /// </summary>
            public int Width
            {
                get { return _width; }
                set { _width = value; }
            }

            /// <summary>
            /// Sets or retrieves the height of the page.
            /// </summary>
            public int Height
            {
                get { return _height; }
                set { _height = value; }
            }            
            #endregion

        } // PageAttribute class
        #endregion

    } // StandardPages
}
